package cn.anc.aoniplayer;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by baobaoding on 2017/6/21.
 */

public class PcmPlayer {
    private static PcmPlayer pcmPlayer = null;
    private AudioTrack audioTrack = null;
    private int audioBufSize = -1;
    private int sampleRate = -1;
    private int channel = -1;
    private int bits = -1;
    private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    private AtomicBoolean isRun = new AtomicBoolean(false);
    private String TAG = PcmPlayer.class.getSimpleName();

    public static PcmPlayer getInstance() {
        if (pcmPlayer == null) {
            pcmPlayer = new PcmPlayer();
        }
        return pcmPlayer;
    }

    /**
     * use default param with sample rate=12KHz, channel=mono, bits=16
     * @return PcmPlayer
     */
    public PcmPlayer setDefaultParam() {
        sampleRate = 48000;
        channel = AudioFormat.CHANNEL_OUT_STEREO;
        bits = AudioFormat.ENCODING_PCM_16BIT;
        return pcmPlayer;
    }

    /**
     * set pcm file param
     * @param _sample_rate 采样率
     * @param _channel 声道数
     * @param _bits 位数
     * @return PcmPlayer
     */
    public PcmPlayer setParam(int _sample_rate, int _channel, int _bits) {
        sampleRate = _sample_rate;
        channel = _channel;
        bits = _bits;
        return pcmPlayer;
    }

    public void playPcmFile(Context context, int resId) {
        try {
            playPcmFile(context.getResources().openRawResource(resId));
        } catch (Exception ex) {
            Log.e(TAG, "playPcmFile: " + ex.getMessage());
        }
    }

    public void playPcmFile(String filepath) {
        try {
            File file = new File(filepath);
            if (!file.exists()) {
                return;
            }
            playPcmFile(new FileInputStream(file));
        } catch (Exception ex) {
            Log.e(TAG, "playPcmFile: " + ex.getMessage());
        }
    }

    private void playPcmFile(final InputStream stream) {
        isRun.set(false);
        singleThreadExecutor.execute(new Runnable() {
            @Override
            public void run() {
                isRun.set(true);
                audioBufSize = AudioTrack.getMinBufferSize(sampleRate, channel, bits);
                if (audioTrack == null) {
                    audioTrack = new AudioTrack(AudioManager.STREAM_RING, sampleRate,
                            channel,
                            bits,
                            audioBufSize,
                            AudioTrack.MODE_STREAM);
                }
                audioTrack.play();
                try {
                    byte[] tempBuffer = new byte[audioBufSize];
                    DataInputStream dis = new DataInputStream(stream);
                    int readCount;
                    while (dis.available() > 0) {
                        readCount= dis.read(tempBuffer);
                        if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
                            continue;
                        }
                        if (!isRun.get()) {
                            break;
                        }
                        if (readCount != 0 && readCount != -1) {
                            audioTrack.write(tempBuffer, 0, readCount);
                        }
                    }
                    dis.close();
                    audioTrack.stop();
                } catch (Exception ex) {
                    Log.e(TAG, "playPcmFile: " + ex.getMessage());
                }
            }
        });
    }

    /*
    void playAllPcmFiles(Activity activity) {
        Field[] fields = R.raw.class.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            try {
                PcmPlayer.getInstance().setDefaultParam().playPcmFile(activity.getBaseContext(), fields[i].getInt(R.raw.class));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }*/
}
